package com.dylan.netty.bio.socket;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author zhangshaojian
 * @date 2022/8/9 14:30
 */
@Slf4j
public class Server {

    private static final ThreadPoolExecutor executor;

    static {
        executor = new ThreadPoolExecutor(4, 8, 20, TimeUnit.MINUTES, new LinkedBlockingDeque<>(30));
    }

    public static void main(String[] args) {
//        singleSocketServer();
        threadSocketServer();
    }

    private static void threadSocketServer() {

        try (
                ServerSocket serverSocket = new ServerSocket(8888)
        ) {
            log.info("服务开启了！！！" + serverSocket);
            while (true) {
                Socket accept = serverSocket.accept();
                log.info("客户端链接成功！！" + accept);
                SocketHandler socketHandler = new SocketHandler(accept);
                executor.execute(socketHandler);
            }
        } catch (Exception ex) {
            log.error("异常咯！！");
        } finally {
        }
    }

    private static void singleSocketServer() {
        BufferedReader reader = null;
        BufferedWriter writer = null;
        try (
                ServerSocket serverSocket = new ServerSocket(8888)
        ) {
            log.info("服务开启了！！！" + serverSocket);
            while (true) {
                Socket accept = serverSocket.accept();
                log.info("客户端链接成功！！" + accept);
                reader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
                writer = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
                log.info("收到客户端消息：");
                String content = reader.lines().collect(Collectors.joining("\n"));
                log.info(content);
                log.info("接收完毕===================");
                writer.write("消息已收到\n这里是服务端 \n" + System.currentTimeMillis());
                writer.flush();
                // 关闭输出流，在socket read到没内容的时候才会返回-1、并不继续阻塞程序
                accept.shutdownOutput();
            }
        } catch (Exception ex) {
            log.error("异常咯！！");
        } finally {
            try {
                IOUtils.close(reader, writer);
            } catch (IOException e) {
                log.error("close server failed");
            }
        }
    }

    public static class SocketHandler implements Runnable {

        private final Socket socket;

        public SocketHandler(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try (
                    BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))
            ) {
                log.info("收到客户端消息：");
                String content = reader.lines().collect(Collectors.joining("\n"));
                log.info(content);
                log.info("接收完毕===================");
                writer.write("消息已收到\n这里是服务端 \n" + System.currentTimeMillis());
                writer.flush();
                socket.shutdownOutput();
            } catch (Exception ex) {
                log.error("异常咯！！");
            } finally {
                log.info("此次回话结束");
            }
        }
    }

}
